package mobilesmil.data;

import java.io.File;

import mobilesmil.view.SmilView;

import android.R;
import android.graphics.Canvas;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaPlayer.OnVideoSizeChangedListener;
import android.util.Log;
import android.view.Gravity;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;
import android.widget.FrameLayout;

public class SmilVideoResource extends SmilResource implements OnPreparedListener, Callback, OnVideoSizeChangedListener {
	public int mPlayState = SmilView.STOPPED;
	private String TAG;
    private MediaPlayer mMediaPlayer;
    private SurfaceView mPreview;
    private SurfaceHolder holder;
    private FrameLayout.LayoutParams mVidParms;
    private String mPath;
    private boolean mIsVideoReadyToBePlayed = false;
	private int mVideoWidth;
	private int mVideoHeight;
	private boolean tryAtPlay = false;

	public SmilVideoResource(String source, SmilRegion smilRegion, int beginTime, int endTime) {
		super(source, smilRegion, beginTime, endTime);
		super.setType("video");
		mPath = SmilResource.ROOT_PATH + source;
		TAG = source;
	}
	
	public SurfaceView prepareVideo(SurfaceView view){
		mPreview = view;
		
		File tmpFile = new File(SmilResource.ROOT_PATH + getSource());
		if(tmpFile.exists()){			
			mVideoWidth = getSmilRegion().getRect().width();
			mVideoHeight = getSmilRegion().getRect().height();
			FrameLayout.LayoutParams vidParms = new FrameLayout.LayoutParams(mVideoWidth, mVideoHeight);
			vidParms.gravity = Gravity.TOP;
			vidParms.topMargin = getSmilRegion().getRect().top;
			if(getBeginTime() > 0)
				vidParms.leftMargin = 0 - mVideoWidth;
			else
				vidParms.leftMargin = getSmilRegion().getRect().left;
			mPreview.setBackgroundColor(Color.TRANSPARENT);
			mPreview.setLayoutParams(vidParms);
			holder = mPreview.getHolder();
	        holder.addCallback(this);
	        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
	        if(!holder.isCreating())
	        	playVideo();
	        
			mVidParms = new FrameLayout.LayoutParams(mVideoWidth, mVideoHeight);
			mVidParms.gravity = Gravity.TOP;
			mVidParms.topMargin = getSmilRegion().getRect().top;
			mVidParms.leftMargin = getSmilRegion().getRect().left;
		}
		
		return mPreview;
	}
	
	public FrameLayout.LayoutParams getLayouParams(){
		return mVidParms;
	}
	
	public SurfaceView getVideoView(){
		return mPreview;
	} 
	
	public void pause(){
		if(mIsVideoReadyToBePlayed && mPlayState == SmilView.PLAYING){
			//mVideoView.pause();
			mMediaPlayer.pause();
			mPlayState = SmilView.PAUSED;
		}
	}

	@Override public void play(Canvas canvas){
		if(!tryAtPlay && mIsVideoReadyToBePlayed && mPlayState != SmilView.PLAYING){
			Log.i("Video", "playing");
			Log.i("HOLDER", String.valueOf(mPreview.getHolder().isCreating()));
			mMediaPlayer.start();
			mPlayState = SmilView.PLAYING;
		}else if(tryAtPlay){
			Log.d(getSource(), "reseting");
			reset();
		}
		else if(!mIsVideoReadyToBePlayed){
			Log.w("Video", "surface not ready");
			reset();
		}
	}
	
	private void reset(){
		tryAtPlay = false;
		mIsVideoReadyToBePlayed = false;
		synchronized(mMediaPlayer){
			mMediaPlayer.reset();
			try {
				mMediaPlayer.setDataSource(mPath);
				mMediaPlayer.setDisplay(holder);
	            mMediaPlayer.prepare();
	            mMediaPlayer.setOnPreparedListener(this);
	            mMediaPlayer.setOnVideoSizeChangedListener(this);
				mPreview.getParent().invalidateChild(mPreview, getSmilRegion().getRect());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	@Override public void stop(Canvas canvas){
		if(mIsVideoReadyToBePlayed && mPlayState > SmilView.STOPPED){
			mMediaPlayer.stop();
			releaseMediaPlayer();
			mPlayState = SmilView.STOPPED;
		}
	}
	
	@Override protected void finalize() throws Throwable {
		releaseMediaPlayer();
		super.finalize();
	}

	private void playVideo() {
        try {
            // Create a new media player and set the listeners
            mMediaPlayer = new MediaPlayer();
            mMediaPlayer.setDataSource(mPath);
            mMediaPlayer.setDisplay(holder);
            mMediaPlayer.prepare();
            mMediaPlayer.setOnPreparedListener(this);
            mMediaPlayer.setOnVideoSizeChangedListener(this);
        } catch (Exception e) {
            Log.e(TAG, "error: " + e.getMessage(), e);
            mMediaPlayer = null;
            System.gc();
            try {
            	mMediaPlayer = new MediaPlayer();
				mMediaPlayer.setDataSource(mPath);
				mMediaPlayer.setDisplay(holder);
	            mMediaPlayer.prepare();
	            mMediaPlayer.setOnPreparedListener(this);
	            mMediaPlayer.setOnVideoSizeChangedListener(this);
			} catch (Exception e1) {
				e1.printStackTrace();
				mPreview.setBackgroundResource(R.drawable.stat_notify_error);
				tryAtPlay = (!tryAtPlay)?true:false;
			}
        }
    }
    
    public void onPrepared(MediaPlayer mediaplayer) {
        Log.d(TAG, "onPrepared called");
        mIsVideoReadyToBePlayed = true;
    }

    public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) {
        Log.d(TAG, "surfaceChanged called");
    }

    public void surfaceDestroyed(SurfaceHolder surfaceholder) {
        Log.d(TAG, "surfaceDestroyed called");
        releaseMediaPlayer();
    }

    public void surfaceCreated(SurfaceHolder holder) {
        Log.d(TAG, "surfaceCreated called");
        playVideo();
    }
	
	private void releaseMediaPlayer() {
        if (mMediaPlayer != null) {
            Log.d(TAG, "releasing media");
            mIsVideoReadyToBePlayed = false;
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }

	@Override public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
		mVideoWidth = width;
        mVideoHeight = height;
        
        holder.setFixedSize(mVideoWidth, mVideoHeight);
	}
}